/* eslint-disable @typescript-eslint/no-use-before-define */
import { DeviceEventEmitter } from 'react-native';
import { filter, find, propEq, reverse, values } from 'ramda';

import { DownloadVideoObject, DownloadVideo } from './types';
import {
  setDlVideo,
  getLatestDlVideo,
  getDlVideo,
  deleteAllDlVideos,
  deleteDlVideo,
  getUnFinishedVideos,
  getFinishedVideos,
  getVideosByParentId,
  unshiftDlVideoQueue,
  getAllDlVideos
} from './downloadStore';
import {
  initDownloadVideo,
  removeDownloadVideoObject,
  deleteAllDownloadVideos,
  deleteOtherVideo,
  pauseDownloadVideoObject,
  initDownloadVideos,
  getCurrentDownloadVideoObject,
  deleteDownloadVideoObject
} from './downloadManage';
import {
  DOWNLOAD_VIDEO_START,
  DOWNLOAD_VIDEO_SUCCESS,
  DOWNLOAD_VIDEO_PROGRESS,
  DOWNLOAD_VIDEO_DELETE,
  DOWNLOAD_VIDEO_PAUSE,
  DOWNLOAD_VIDEO_FAIL
} from './constant';
import Log from '../../common/log';

const TAG = 'downloadOperation';

export const dlVideoOnSuccess = (data: DownloadVideoObject): void => {
  console.log('RUA SUCCESS');

  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_SUCCESS, { ...data });
  setDlVideo({ ...data, tsList: [] });
  // moveToEnd(data.id);
  removeDownloadVideoObject();
  continueDownload();
};
export const dlVideoOnProgress = (data: DownloadVideoObject): void => {
  console.log('RUA PROGRESS');
  setDlVideo(data);
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_PROGRESS, { ...data });
};
export const dlVideoOnDelete = (data: DownloadVideoObject): void => {
  console.log('RUA DELETE');
  deleteDlVideo(data.id);
  removeDownloadVideoObject();
  setTimeout((): void => {
    continueDownload();
    DeviceEventEmitter.emit(DOWNLOAD_VIDEO_DELETE, { ...data });
  }, 100);
};
export const dlVideoOnStart = (data: DownloadVideoObject): void => {
  console.log('RUA START');
  setDlVideo(data);
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_START, { ...data });
};
export const dlVideoOnPause = (data: DownloadVideoObject): void => {
  console.log('RUA PAUSE');
  setDlVideo(data);
  removeDownloadVideoObject();
  setTimeout((): void => {
    continueDownload();
    DeviceEventEmitter.emit(DOWNLOAD_VIDEO_PAUSE, { ...data });
  }, 100);
};
export const dlVideoOnFail = (data: DownloadVideoObject): void => {
  console.log('RUA FAIL');
  setDlVideo(data);
  removeDownloadVideoObject();

  failDownloadByParentId(data.parentId);
  continueDownload();
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_FAIL, { ...data });
};

export const continueDownload = (): void => {
  console.log('RUA CONTINUE BACKGROUND');
  setTimeout((): void => {
    const latestVideo = getLatestDlVideo();
    if (latestVideo) {
      initDownloadVideo({
        ...latestVideo,
        onSuccess: dlVideoOnSuccess,
        onProgress: dlVideoOnProgress,
        onDelete: dlVideoOnDelete,
        onStart: dlVideoOnStart,
        onPause: dlVideoOnPause,
        onFail: dlVideoOnFail,
        getStore: getDlVideo,
        init: (data): void => {
          setDlVideo(data);
        }
      });
    }
  }, 100);
};
export const startDownload = (id: number): void => {
  const video = getDlVideo(id);

  if (video) {
    initDownloadVideo({
      ...video,
      onSuccess: dlVideoOnSuccess,
      onProgress: dlVideoOnProgress,
      onDelete: dlVideoOnDelete,
      onStart: dlVideoOnStart,
      onPause: dlVideoOnPause,
      onFail: dlVideoOnFail,
      getStore: getDlVideo,
      init: (data): void => {
        setDlVideo(data);
      }
    });
  }
};
export const dlVideoDeleteOther = (id: number | string): void => {
  const deleteVideo = getDlVideo(id);
  if (deleteVideo) {
    deleteOtherVideo(deleteVideo.folderName);
  }
  deleteDlVideo(id);
};
export const dlVideoDeleteAll = (): void => {
  console.log('RUA DELETE ALL');
  removeDownloadVideoObject();
  deleteAllDownloadVideos();
  deleteAllDlVideos();
};
export const getDlVideoPath = (id: number): string => {
  let path = '';
  const video = getDlVideo(id);
  if (video) {
    path = video.m3u8Path;
  }
  return path;
};
export const startDownloadOther = (id: number): void => {
  const startVideo = getDlVideo(id);
  if (startVideo) {
    setDlVideo({ ...startVideo, isPaused: false, isFailed: false });
  }
};
export const startDownloadAll = (): void => {
  console.log('RUA start all');
  const videos = getUnFinishedVideos();
  videos.forEach((item: DownloadVideoObject): void =>
    setDlVideo({ ...item, isPaused: false, isFailed: false })
  );
  continueDownload();
};
export const pauseDownloadOther = (id: number): void => {
  const pauseVideo = getDlVideo(id);
  if (pauseVideo) {
    setDlVideo({ ...pauseVideo, isPaused: true });
  }
};
export const pauseDownloadAll = (): void => {
  console.log('RUA pause all');

  pauseDownloadVideoObject();
  const videos = getUnFinishedVideos();
  videos.forEach((item: DownloadVideoObject): void =>
    setDlVideo({ ...item, isPaused: true })
  );
};

export const getVideoIsFinished = (video: DownloadVideoObject): boolean => {
  const tsHaveDone = video.tsList.every((item): boolean => item.hasDone);
  return video.indexHasDone && video.keyHasDone && tsHaveDone;
};

// 过滤已经不需要的下载任务并删除
export const filterExcludeVideos = (downloadVideos: DownloadVideo[]): void => {
  if (downloadVideos.length > 0) {
    const { parentId } = downloadVideos[0];
    const allVideos = values(getVideosByParentId(parentId));

    const filterVideos = (item: DownloadVideoObject): boolean =>
      !find((video): boolean => item.id === video.id, downloadVideos);

    const excludeVideos = filter(filterVideos)(allVideos);

    excludeVideos.forEach((item): void => {
      dlVideoDeleteOther(item.id);
    });
  }
};

export const startDownloadVideoTasks = (
  videos: DownloadVideo[],
  isPrior = false
): void => {
  const downloadedVideos = getFinishedVideos();

  const filterFinishedVideos = (item: DownloadVideo): boolean => {
    for (let i = 0; i < downloadedVideos.length; i += 1) {
      if (downloadedVideos[i].id === item.id) {
        return false;
      }
    }
    return true;
  };

  // 过滤已下载的文件
  const downloadVideos = filter(filterFinishedVideos)(videos);

  Log.i(
    TAG,
    JSON.stringify({
      event: 'initDownloadVideos',
      downloadVideos
    })
  );

  if (downloadVideos.length) {
    initDownloadVideos({
      downloadVideos: isPrior ? reverse(downloadVideos) : downloadVideos, // 如果是需要立刻下载的需要反转数组
      onSuccess: dlVideoOnSuccess,
      onProgress: dlVideoOnProgress,
      onDelete: dlVideoOnDelete,
      onStart: dlVideoOnStart,
      onPause: dlVideoOnPause,
      onFail: dlVideoOnFail,
      getStore: getDlVideo,
      init: (data): void => {
        if (isPrior) {
          // 如果是需要立刻下载则从头放入下载队列
          unshiftDlVideoQueue(data);
        } else {
          setDlVideo(data);
        }
      },
      isPrior
    });
  }
};

export const startDownloadByParentId = (parentId: number): void => {
  const videos = getUnFinishedVideos();
  const parentVideos = filter(propEq('parentId', parentId))(videos);
  parentVideos.forEach((item: DownloadVideoObject): void =>
    setDlVideo({ ...item, isPaused: false, isFailed: false })
  );
  Log.i(
    TAG,
    JSON.stringify({
      event: 'startDownloadByParentId',
      parentId,
      parentVideos: parentVideos.map(
        ({
          id,
          url,
          folderName,
          m3u8Path,
          progress,
          indexHasDone,
          keyHasDone,
          serverDir
        }) => ({
          id,
          url,
          folderName,
          parentId,
          m3u8Path,
          progress,
          indexHasDone,
          keyHasDone,
          serverDir
        })
      )
    })
  );
  continueDownload();
};

export const pauseDownloadByParentId = (parentId: number): void => {
  console.log('RUA pause by parentId');

  const downloadingVideo = getCurrentDownloadVideoObject();

  if (downloadingVideo && downloadingVideo.parentId === parentId) {
    pauseDownloadVideoObject();
  }
  const videos = getUnFinishedVideos();
  const parentVideos = filter(propEq('parentId', parentId))(videos);
  parentVideos.forEach((item: DownloadVideoObject): void =>
    setDlVideo({ ...item, isPaused: true })
  );
};

export const deleteDownloadByParentId = (parentId: number): void => {
  const downloadingVideo = getCurrentDownloadVideoObject();

  if (downloadingVideo && downloadingVideo.parentId === parentId) {
    deleteDownloadVideoObject();
  }

  const videos = getAllDlVideos();
  const parentVideos = filter(propEq('parentId', parentId))(videos);
  parentVideos.forEach((item: DownloadVideoObject): void => {
    dlVideoDeleteOther(item.id);
  });
};

export const failDownloadByParentId = (parentId: number): void => {
  console.log('RUA fail by parentId');

  const downloadingVideo = getCurrentDownloadVideoObject();

  if (downloadingVideo && downloadingVideo.parentId === parentId) {
    pauseDownloadVideoObject();
  }
  const videos = getUnFinishedVideos();
  const parentVideos = filter(propEq('parentId', parentId))(videos);
  parentVideos.forEach((item: DownloadVideoObject): void =>
    setDlVideo({ ...item, isFailed: true })
  );
};
